﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using RS.Caching;
using RS.Common;
using RS.Logger;
using RS.SAAS.Common.Configuration;
using RS.SAAS.Common.Cookies;
using RS.SAAS.WebService.Consumer;
using RS.SAAS.WebService.Entities;
using RS.Web;
using TimeManagementMobile.Models;

namespace TimeManagementMobile.Controllers
{
    public class HomeController : ControllerBase
    {
        private const string ServersXmlFile = "servers.xml";

        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult GetMinVersion(string platform)
        {
            var res = new AppVersionInfo();
            res.MinVersion = "0.0";
            if (string.IsNullOrWhiteSpace(platform) ||
                platform.Equals("none", StringComparison.InvariantCultureIgnoreCase))
                return Json(res, JsonRequestBehavior.AllowGet);

            try
            {
                string serversFileContent = GetServersFileContent();

                var doc = new XmlDocument();
                doc.LoadXml(serversFileContent);
                XmlNode serversNode = doc.SelectNodes("servers").Item(0);
                if (serversNode == null)
                    return Json(res);

                res.MinVersion = serversNode.Attributes[string.Format("min-version-{0}", platform)].Value.ToLower();
                res.AppStoreUrl = ConfigurationManager.AppSettings[string.Format("{0}-app-url", platform)];
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }

            return Json(res, JsonRequestBehavior.AllowGet);
        }

        public ActionResult GetConnectionUrl(string serverCode)
        {
            Server server = null;
            if (string.IsNullOrEmpty(serverCode))
                return Json(server, JsonRequestBehavior.AllowGet);

            try
            {
                IEnumerable<Server> servers = GetServers();
                server = servers.FirstOrDefault(el => el.Code.Equals(serverCode, StringComparison.InvariantCultureIgnoreCase));
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }

            return Json(server, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult GetAvailableCompanies(string server, string username, string password, string liso)
        {
            Response<List<Company>> response;

            try
            {
                Guid tmId = ConfigurationAccessor.Applications.GetTimeManagementId();
                Consumer consumer = GetConsumer(server, liso);
                response = consumer.GetCompaniesTheUserHasAccessToForApplication(username, password, tmId, null);
            }
            catch (Exception ex)
            {
                response = ErrorProcessor.ProcessError<List<Company>>(ex);
            }

            return Json(response.Data);
        }

        [HttpPost]
        public ActionResult GetConnectionData(string server, string username, string password, Guid companyId, string liso)
        {
            var response = new Response<Dictionary<string, string>>();
            try
            {
                Guid tmId = ConfigurationAccessor.Applications.GetTimeManagementId();
                Consumer consumer = GetConsumer(server, liso);
                Response<Uri> data = consumer.GetApplicationConnectionUrl(string.Empty, companyId, username, password);
                if (data.Exception != null)
                    throw data.Exception;

                response.Data = new Dictionary<string, string>();
                if (data.Data != null && !string.IsNullOrWhiteSpace(data.Data.Query))
                {
                    NameValueCollection parameters = HttpUtility.ParseQueryString(data.Data.Query);
                    foreach (string item in parameters.AllKeys)
                        response.Data.Add(item, parameters[item]);
                }

                if (!response.Data.ContainsKey("app_id"))
                    response.Data.Add("app_id", tmId.ToString());

                if (response.Data.ContainsKey("liso"))
                    CookiesManager.CultureName = response.Data["liso"];
            }
            catch (Exception ex)
            {
                response = new Response<Dictionary<string, string>>(ex);
                Log.Error(ex);
            }

            return Json(response.Data);
        }

        private string GetServersFileContent()
        {
            string serversFileContent = (Cache.Default.Get("ServersFile") ?? string.Empty).ToString();
            if (!string.IsNullOrWhiteSpace(serversFileContent))
                return serversFileContent;

            try
            {
                string xmlFilePath = HttpContext.Server.MapPath("~/" + ServersXmlFile);
                serversFileContent = System.IO.File.ReadAllText(xmlFilePath);
                Cache.Default.Set("ServersFile", serversFileContent);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }

            return serversFileContent;
        }

        private IEnumerable<Server> GetServers()
        {
            var servers = Cache.Default.Get("Servers") as List<Server>;
            if (servers != null)
                return servers;

            var data = new List<Server>();
            try
            {
                string serversFileContent = GetServersFileContent();
                if (string.IsNullOrWhiteSpace(serversFileContent))
                    return data;

                var doc = new XmlDocument();
                doc.LoadXml(serversFileContent);
                XmlNodeList nodes = doc.SelectNodes("//server");
                if (nodes != null)
                    data.AddRange(from XmlNode item in nodes
                        let xmlAttributeCollection = item.Attributes
                        where xmlAttributeCollection != null
                        select new Server
                        {
                            Code = xmlAttributeCollection["code"].Value.ToLower(),
                            ApplicationUrl = new Uri(xmlAttributeCollection["applicationAddress"].Value),
                            ServiceAddress = new Uri(xmlAttributeCollection["serviceAddress"].Value),
                            IsSAAS = DataConverter.ToBoolean(xmlAttributeCollection["isSAAS"].Value),
                            ProfileId = DataConverter.ToNullableGuid(xmlAttributeCollection.GetNamedItem("profile") == null ? string.Empty : xmlAttributeCollection["profile"].Value)
                        });

                Cache.Default.Set("Servers", data);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }

            return data;
        }

        private Consumer GetConsumer(string serverCode, string liso = "")
        {
            var profileId = new Guid?();

            Server server = GetServers().FirstOrDefault(el => el.Code.Equals(serverCode, StringComparison.InvariantCultureIgnoreCase));
            if (server != null)
                profileId = server.ProfileId;

            ConfigurationAccessor.SetCurrentProfile(profileId);

            Guid tmId = ConfigurationAccessor.Applications.GetTimeManagementId();
            string secretKey = BaseConfigurationAccessor.Get(tmId.ToString());
            string saasServiceUrl = ConfigurationAccessor.GetSAASServiceUrl();

            Log.Info("Creating consumer with serviceUrl: {0}", saasServiceUrl);
            return new Consumer(tmId, secretKey, liso, saasServiceUrl, Guid.Empty);
        }
    }
}